package com.example.springmvc.config;

import com.example.springmvc.exception.AuthorizationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 * 从 Header 获取 token 并解析
 *
 * @author 凡行
 */
@Component
public class JwtMethodArgumentResolver implements HandlerMethodArgumentResolver {
    private final Logger log = LoggerFactory.getLogger(JwtMethodArgumentResolver.class);

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(SessionUser.class) && parameter.getParameterType().isInstance(Long.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        Long result = this.resolveSessionUser(webRequest);
        log.debug("method: {}, session-user: {}", parameter.getMethod(), result);
        if (result != null) {
            return result;
        }
        // 是否必须
        SessionUser anno = parameter.getParameterAnnotation(SessionUser.class);
        if (anno == null || !anno.required()) {
            return null;
        }
        throw new AuthorizationException();
    }

    protected Long resolveSessionUser(NativeWebRequest webRequest) {
        return (Long) webRequest.getAttribute(SessionUser.SESSION_ATTR_NAME, RequestAttributes.SCOPE_REQUEST);
    }
}
